Applying throw and throws in Java
Course: Core Java Training
Topic: Applying throw and throws in Java
Course Link: Core Java Training Course
Demo Link: Register for a Course Demo
JustAcademy Website: Visit JustAcademy
1. Introduction to throw and throws
Exception handling is an important feature of Java that allows developers to manage errors and unexpected conditions during program execution. Java provides several keywords for exception handling, including try, catch, finally, throw, and throws.
The throw and throws keywords are closely related, but they serve different purposes. The throw keyword is used to explicitly throw a particular exception object, while the throws keyword declares the exception types that a method or constructor may pass to its caller.
Understanding these keywords helps developers validate input, communicate failures clearly, create custom exceptions, and design reliable Java applications.
2. Learning Objectives
- Understand the purpose of the
throw keyword.
- Learn how the
throws keyword works in method declarations.
- Differentiate between
throw and throws.
- Understand how checked and unchecked exceptions behave.
- Learn how to propagate exceptions between methods.
- Use custom exceptions with
throw and throws.
- Understand common mistakes and exception-handling best practices.
- Practice exception handling through Java programs and exercises.
3. What Is the throw Keyword?
The throw keyword is used to explicitly throw a throwable object from a method or code block. It is commonly used when a program detects an invalid value, a violated business rule, or another condition that should interrupt normal execution.
The object being thrown must be an instance of Throwable or one of its subclasses, such as Exception, RuntimeException, or Error.
Syntax
throw new ExceptionType("Descriptive error message");
In this syntax:
throw is the keyword used to throw the exception.
new creates an exception object.
ExceptionType is the class of the exception.
- The message describes the reason for the failure.
Example: Using throw
public class ThrowExample {
public static void main(String[] args) {
int age = 16;
if (age < 18) {
throw new IllegalArgumentException(
"Age must be at least 18."
);
}
System.out.println("Access granted.");
}
}
Output
Exception in thread "main" java.lang.IllegalArgumentException:
Age must be at least 18.
Explanation: The program checks whether the age is below 18. Because the condition is true, it throws an IllegalArgumentException. Since the exception is not caught, it propagates out of the main() method, and the statement that prints "Access granted." is not executed.
4. What Is the throws Keyword?
The throws keyword is used in a method or constructor declaration to specify exception types that the method may propagate to its caller. It is especially important for checked exceptions, which Java requires the program to catch or declare.
When a method declares a checked exception using throws, the caller must either handle the exception with an appropriate try-catch block or declare it in its own method signature.
Syntax
returnType methodName() throws ExceptionType {
// Method statements
}
Example: Using throws
import java.io.IOException;
public class ThrowsExample {
static void performOperation() throws IOException {
throw new IOException("Unable to complete the operation.");
}
public static void main(String[] args) {
try {
performOperation();
} catch (IOException e) {
System.out.println("Handled: " + e.getMessage());
}
}
}
Output
Handled: Unable to complete the operation.
Explanation: The method performOperation() declares that it may throw an IOException. It explicitly throws the exception, and the calling method handles it using a catch block.
Important: The throws declaration does not itself throw an exception. It declares the types of exceptions that may be propagated from the method.
5. Difference Between throw and throws
| Basis |
throw |
throws |
| Purpose |
Explicitly throws a throwable object. |
Declares throwable types that a method or constructor may propagate. |
| Location |
Inside a method, constructor, or code block. |
In a method or constructor declaration. |
| Followed by |
A throwable object or an expression that produces one. |
One or more exception types. |
| Number |
Throws one object at a time. |
Can declare multiple exception types separated by commas. |
| Checked exceptions |
A checked exception must be handled or declared. |
Can declare checked exceptions to satisfy the compiler requirement. |
| Unchecked exceptions |
Can throw unchecked exceptions explicitly. |
Unchecked exceptions can be declared, but the declaration is not required. |
| Example |
throw new IOException("Failed"); |
void read() throws IOException |
6. Understanding Checked and Unchecked Exceptions
To use throw and throws correctly, it is important to understand the difference between checked and unchecked exceptions.
6.1 Checked Exceptions
Checked exceptions are checked by the compiler. A method must catch them or declare them if they may propagate beyond that method.
Common examples include:
IOException
FileNotFoundException
SQLException
ClassNotFoundException
InterruptedException
Example
import java.io.IOException;
public class CheckedExceptionExample {
static void readData() throws IOException {
throw new IOException("Data could not be read.");
}
public static void main(String[] args) {
try {
readData();
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
}
The checked exception is declared by readData() and handled by its caller.
6.2 Unchecked Exceptions
Unchecked exceptions include RuntimeException and its subclasses. Java does not require methods to catch or declare these exceptions.
Common examples include:
ArithmeticException
NullPointerException
NumberFormatException
IllegalArgumentException
ArrayIndexOutOfBoundsException
Example
public class UncheckedExceptionExample {
static void validateNumber(int number) {
if (number < 0) {
throw new IllegalArgumentException(
"Number cannot be negative."
);
}
}
public static void main(String[] args) {
try {
validateNumber(-5);
} catch (IllegalArgumentException e) {
System.out.println(e.getMessage());
}
}
}
The method throws an unchecked exception when the argument is negative. It does not need a throws declaration, although the caller may still catch the exception.
7. Using throw and throws Together
The two keywords can be used together when a method explicitly throws a checked exception and declares that exception in its signature.
import java.io.IOException;
public class ThrowThrowsExample {
static void checkFileStatus(boolean available)
throws IOException {
if (!available) {
throw new IOException("The required file is unavailable.");
}
System.out.println("File is available.");
}
public static void main(String[] args) {
try {
checkFileStatus(false);
} catch (IOException e) {
System.out.println("Error: " + e.getMessage());
}
}
}
Output
Error: The required file is unavailable.
Step-by-Step Explanation
- The
main() method calls checkFileStatus(false).
- The method checks whether the file is available.
- Since the argument is false, the method throws an
IOException.
- The
throws IOException declaration indicates that the checked exception may propagate to the caller.
- The catch block in
main() handles the exception and prints its message.
8. Declaring Multiple Exceptions with throws
A method can declare more than one exception type in its throws clause. The exception types are separated by commas.
Syntax
void processData() throws IOException, SQLException {
// Operations that may produce either exception
}
Example
import java.io.IOException;
import java.sql.SQLException;
public class MultipleThrowsExample {
static void processData(boolean fileProblem, boolean databaseProblem)
throws IOException, SQLException {
if (fileProblem) {
throw new IOException("File processing failed.");
}
if (databaseProblem) {
throw new SQLException("Database operation failed.");
}
System.out.println("Data processed successfully.");
}
public static void main(String[] args) {
try {
processData(true, false);
} catch (IOException e) {
System.out.println("File error: " + e.getMessage());
} catch (SQLException e) {
System.out.println("Database error: " + e.getMessage());
}
}
}
Output
File error: File processing failed.
Explanation: The method declares both possible checked exception types. Because the first argument is true, it throws an IOException. The matching catch block handles the exception, and the second catch block is skipped.
9. Exception Propagation Using throws
Exception propagation occurs when a method does not handle an exception and allows it to move to its caller. The throws keyword can document this behavior and satisfy the compiler for checked exceptions.
import java.io.IOException;
public class ExceptionPropagationExample {
static void methodC() throws IOException {
throw new IOException("Failure in methodC.");
}
static void methodB() throws IOException {
methodC();
}
static void methodA() throws IOException {
methodB();
}
public static void main(String[] args) {
try {
methodA();
} catch (IOException e) {
System.out.println("Handled in main: " + e.getMessage());
}
}
}
Output
Handled in main: Failure in methodC.
Explanation
methodC() throws the exception.
methodB() allows it to propagate.
methodA() also allows it to propagate.
main() catches and handles the exception.
Exception propagation allows lower-level methods to report a failure without needing to decide how the application should respond. A higher-level method can then handle the problem in a way appropriate to the application.
10. Creating Custom Exceptions with throw and throws
Custom exceptions allow developers to represent specific business rules or application failures. A checked custom exception typically extends Exception, while an unchecked custom exception extends RuntimeException.
Example: Invalid Marks Exception
class InvalidMarksException extends Exception {
public InvalidMarksException(String message) {
super(message);
}
}
public class StudentMarksExample {
static void validateMarks(int marks)
throws InvalidMarksException {
if (marks < 0 || marks > 100) {
throw new InvalidMarksException(
"Marks must be between 0 and 100."
);
}
System.out.println("Marks are valid.");
}
public static void main(String[] args) {
try {
validateMarks(120);
} catch (InvalidMarksException e) {
System.out.println("Validation failed: " + e.getMessage());
}
}
}
Output
Validation failed: Marks must be between 0 and 100.
Explanation
InvalidMarksException is a custom checked exception.
- The method declares it using
throws InvalidMarksException.
- The method explicitly throws it when marks fall outside the valid range.
- The caller handles the exception in a catch block.
11. Using throw in Constructors
The throw keyword can be used inside a constructor to reject invalid data when an object is created. This helps protect an object's state from being initialized with inappropriate values.
public class Product {
private String name;
private double price;
public Product(String name, double price) {
if (name == null || name.trim().isEmpty()) {
throw new IllegalArgumentException(
"Product name cannot be empty."
);
}
if (!Double.isFinite(price) || price <= 0) {
throw new IllegalArgumentException(
"Product price must be a finite positive value."
);
}
this.name = name;
this.price = price;
}
public void display() {
System.out.println("Product: " + name);
System.out.println("Price: " + price);
}
public static void main(String[] args) {
try {
Product product = new Product("Laptop", -500.0);
product.display();
} catch (IllegalArgumentException e) {
System.out.println("Invalid product: " + e.getMessage());
}
}
}
Output
Invalid product: Product price must be a finite positive value.
Explanation: The constructor validates its arguments before assigning them to the object's fields. When the price is invalid, it throws an IllegalArgumentException, preventing creation of an invalid product object.
12. Using throw with Conditional Statements
Conditional statements are often used with throw to enforce validation rules. When a condition is violated, the program throws an exception rather than continuing with invalid data.
public class PasswordValidator {
static void validatePassword(String password) {
if (password == null) {
throw new IllegalArgumentException(
"Password cannot be null."
);
}
if (password.length() < 8) {
throw new IllegalArgumentException(
"Password must contain at least 8 characters."
);
}
System.out.println("Password format is valid.");
}
public static void main(String[] args) {
try {
validatePassword("abc");
} catch (IllegalArgumentException e) {
System.out.println(e.getMessage());
}
}
}
Output
Password must contain at least 8 characters.
This example demonstrates validation logic. A real authentication system should also apply secure password-storage practices and additional security checks.
13. Common Mistakes When Using throw and throws
| Mistake |
Why It Is Incorrect |
Correct Approach |
Using throw without a throwable object |
The keyword requires an object compatible with Throwable. |
Use throw new IllegalArgumentException("Invalid input");. |
Using throws inside a method body |
throws belongs in the method or constructor declaration. |
Use throw to throw an exception inside the body. |
| Not handling a checked exception |
The compiler reports an error if a checked exception is neither caught nor declared. |
Add a suitable catch block or declare the exception with throws. |
| Assuming throws handles the exception |
The declaration does not handle an exception. |
Catch it at an appropriate level or allow it to propagate. |
| Declaring unnecessary exception types |
Unnecessary declarations can make APIs harder to understand. |
Declare only meaningful exception types. |
| Throwing generic exceptions for every failure |
The actual problem may become less clear. |
Use an appropriate standard exception or a meaningful custom exception. |
| Ignoring the original cause |
Diagnostic information may be lost when an exception is wrapped. |
Preserve the cause when translating exceptions. |
| Using exceptions for routine decisions |
Normal application logic becomes harder to follow. |
Use conditional statements for expected routine conditions when appropriate. |
14. Best Practices for Using throw and throws
- Use
throw when a specific condition requires an exception to be raised.
- Use
throws to declare checked exceptions that may propagate to callers.
- Choose meaningful exception classes rather than using one generic type for every problem.
- Write clear and useful exception messages.
- Validate arguments at suitable boundaries, such as public methods and constructors.
- Use checked exceptions when callers are expected to handle a condition explicitly; use unchecked exceptions for appropriate programming-contract violations.
- Catch exceptions at the layer that can recover or respond meaningfully.
- Preserve the original cause when wrapping an exception.
- Avoid empty catch blocks and do not silently ignore failures.
- Do not catch
Throwable or Error casually as a substitute for correct error handling.
- Write tests for valid inputs, invalid inputs, and failure scenarios.
15. Practical Exercise 1: Age Validation
Task: Create a Java program that checks whether a person is eligible to register for an age-restricted service.
Requirements:
- Create a method named
validateAge().
- Accept an integer age as a parameter.
- Throw an
IllegalArgumentException if the age is negative.
- Throw an
IllegalArgumentException if the age is below 18.
- Use a catch block in
main() to display the message.
- Test the program with valid and invalid values.
16. Practical Exercise 2: File Reading
Task: Write a method that reads a text file and declares IOException using throws.
Requirements:
- Use the
Files.readString() method from java.nio.file.Files.
- Declare
throws IOException in the reading method.
- Handle the exception in the calling method.
- Display a useful message if the file cannot be read.
- Test the program with an existing file and a missing file.
17. Practical Exercise 3: Custom Exception
Task: Create an InsufficientBalanceException class for a banking application.
Requirements:
- Extend
Exception.
- Add a constructor that accepts a message.
- Create a withdrawal method that declares the exception using
throws.
- Use
throw when the requested withdrawal exceeds the balance.
- Handle the exception in the calling code.
- Display the remaining balance when the withdrawal succeeds.
18. Mini Project: Employee Salary Validation
Objective: Build a simple employee salary validation program that uses throw and throws to reject invalid salary values.
class InvalidSalaryException extends Exception {
public InvalidSalaryException(String message) {
super(message);
}
}
public class EmployeeSalary {
static void validateSalary(double salary)
throws InvalidSalaryException {
if (!Double.isFinite(salary) || salary <= 0) {
throw new InvalidSalaryException(
"Salary must be a finite positive amount."
);
}
System.out.println("Salary accepted: " + salary);
}
public static void main(String[] args) {
double salary = -25000.0;
try {
validateSalary(salary);
} catch (InvalidSalaryException e) {
System.out.println("Salary validation failed: " + e.getMessage());
}
}
}
Expected Output
Salary validation failed: Salary must be a finite positive amount.
Project Enhancements
- Accept salary values from the user.
- Validate that the salary is a finite positive number.
- Display an appropriate message for invalid values.
- Extend the project to calculate annual salary from monthly salary.
- Add a custom exception for invalid employee identification numbers.
- Write tests for valid, negative, zero, NaN, and infinite salary values.
19. Interview Questions and Answers
Q1. What is the difference between throw and throws in Java?
Answer: throw explicitly throws a throwable object, whereas throws declares the exception types that a method or constructor may propagate to its caller.
Q2. Can we use throw and throws together?
Answer: Yes. A method can declare a checked exception with throws and explicitly throw an instance of that exception using throw.
Q3. Can a method declare multiple exceptions using throws?
Answer: Yes. Multiple exception types can be declared in a method signature, separated by commas.
Q4. Is the throws keyword mandatory for unchecked exceptions?
Answer: No. Unchecked exceptions do not need to be declared, although Java permits their declaration.
Q5. Is the throw keyword used only for custom exceptions?
Answer: No. It can throw built-in exceptions, custom exceptions, and other throwable objects.
Q6. What happens when a checked exception is thrown without being caught or declared?
Answer: If a checked exception can propagate out of a method without being caught or declared, the compiler reports an error.
Q7. Does throws handle an exception?
Answer: No. It declares that an exception may propagate. Handling requires an appropriate catch block or another suitable mechanism at a higher level.
Q8. Can constructors use throws?
Answer: Yes. Constructors can declare checked exceptions using throws, and callers must handle or declare those exceptions.
Q9. Can throw be used inside a constructor?
Answer: Yes. A constructor can throw an exception when the supplied arguments violate validation rules.
Q10. Why are custom exceptions useful?
Answer: They represent application-specific failures clearly and allow callers to distinguish particular business conditions from other errors.
20. Quick Revision Checklist
throw explicitly throws a throwable object.
throws declares throwable types in a method or constructor signature.
- A checked exception must be caught or declared.
- Unchecked exceptions do not require a
throws declaration.
- A method can declare multiple exception types separated by commas.
- Exceptions can propagate through multiple methods until a matching handler is found.
- Custom exceptions can represent application-specific problems.
- Constructors can validate input and throw exceptions.
- Meaningful exception messages improve debugging.
- Exception causes should be preserved when useful.
- Test both successful execution and exceptional conditions.
21. Conclusion
The throw and throws keywords are fundamental tools for exception handling in Java. The throw keyword allows a program to raise an exception when a condition is violated, while throws declares exception types that may be passed to the calling method.
By using these keywords correctly, developers can validate input, create custom exceptions, propagate failures through method calls, and keep error-handling logic organized. Combining these techniques with clear messages, appropriate exception types, and thorough testing helps create more reliable Java applications.
Continue learning Java programming through the Core Java Training Course, register for a course demo, or visit the JustAcademy website.